﻿
/*============== simpleIRC - http://matthias.van-eeghem.com/ ==============*
 *                                                                         *
 *  File: ChannelWindow.cs                                                        *
 *  Project: simpleIRC                                                     *
 *  Author(s): Matthias Van Eeghem <matthias@van-eeghem.com>               *
 *                                                                         *
 * ========================================================================*
 *                                                                         *
 *  This program is free software: you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation, either version 3 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 *                                                                         *
===========================================================================*/

using System;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Threading;
using simpleIRC;

namespace simpleIRC.UI
{
    /// <summary>
    /// This class contains all UI stuff related to classes 
    /// </summary>
    
    public class ChannelWindow
    {
        /// <summary>
        /// This variable holds a reference to the MainWindow class
        /// </summary>
        MainWindow mainWindow = null;

        /// <summary>
        /// The name of the ChannelWindow
        /// </summary>
        private string Name;

        /// <summary>
        /// The ServerIndex the channel is on
        /// </summary>
        private int ServerIndex;

        /// <summary>
        /// The Channel object this ChannelWindow links to
        /// </summary>
        private Channel Channel;

        /// <summary>
        /// This TreeViewItem holds the TreeViewItem for this ChannelWindow object
        /// </summary>
        public TreeViewItem ChannelTreeViewItem { get; private set; }

        /// <summary>
        /// This static variable holds a list of all the ChannelWindows created
        /// </summary>
        public static List<ChannelWindow> List = new List<ChannelWindow>();

        /// <summary>
        /// The constructor of the ChannelWindow class
        /// </summary>
        /// <param name="name">The channel name</param>
        /// <param name="serverIndex">The serverindex the channel is on</param>
        /// <param name="channelIndex">The channel index of the channel this object references</param>
        /// <param name="parentWindow">The reference to the MainWindow object</param>
        
        public ChannelWindow(string name, int serverIndex, int channelIndex, MainWindow parentWindow)
        {
            Name = name;
            ServerIndex = serverIndex;
            mainWindow = parentWindow;
            Channel = Core.ChannelList[channelIndex];

            // Add this object to the ChannelWindowList
            List.Add(this);
        }

        /// <summary>
        /// This method creates the actual TreeViewItem to the ChannelsTreeView
        /// </summary>

        public void Create()
        {
            mainWindow.CurrentChannelWindow = Core.ChannelList.Count;

            ChannelTreeViewItem = new TreeViewItem();
            ChannelTreeViewItem.Header = Name;

            // Create a new context menu.
            ContextMenu RightClickMenu = new ContextMenu();
            // We need to make a copy to pass it on as a reference to the AddRightClickEvent()
            TreeViewItem ChannelTreeViewItemCopy = ChannelTreeViewItem;
            mainWindow.UserInterface.AddRightClickEvent(ref ChannelTreeViewItemCopy, "Part", mainWindow.UserInterface.ContextMenu_PartChannel);

            // Expand the ServerTreeViewItem
            ServerWindow.List[ServerIndex].ServerTreeViewItem.IsExpanded = true;
            // Add the channel to the ServerList and select it
            ServerWindow.List[ServerIndex].ServerTreeViewItem.Items.Add(ChannelTreeViewItem);
            // Select the channel
            ChannelTreeViewItem.IsSelected = true;

            // Sort the channels if that setting is set to true
            if (mainWindow.Config.Settings["SortChannels"] == "true")
            {
                ServerWindow.List[ServerIndex].ServerTreeViewItem.Items.SortDescriptions.Add(new System.ComponentModel.SortDescription("Header", System.ComponentModel.ListSortDirection.Ascending));
            }
        }

        /// <summary>
        /// This function loads all the users (in the right hand userbar) for a certain channel.
        /// </summary>

        public void LoadUsers()
        {
            // Get an array of users on the channel
            string[] Names = Channel.UserList.Split(new Char[] { ' ' });

            // This dictionary will hold each name that will work as header for the TreeViewItem as header
            // and as value for that key the string that will work as the value as the name property
            // The main difference between these two is that the second will have no invalid characters
            // and that it will have a sorting character prepended to the string, so sorting alphabetically
            // will work with the different userlevels
            Dictionary<string, string> ChannelNames = new Dictionary<string, string>();

            // Loop through all the names.
            foreach (string Name in Names)
            {
                // Check if we have a valid name
                if (Name.Length >= 1 && Name != "")
                {
                    string NewName = Name;

                    // We only prepend the "highest" level to the user's name
                    if (Name[0] == '~' || Name[0] == '&' || Name[0] == '@' || Name[0] == '%' || Name[0] == '+')
                    {
                        // Get the highest level, and strip the rest from the user's name
                        NewName = Name[0] + Channel.GetNameWithoutRights(Name);
                    }

                    // We prepend the Item.Name property with a letter indicating the user's level
                    // We do this so we can sort the entire UsersTreeView on the Item.Name property
                    char SortCharacter = (char)MainWindow.SortCharacters.NoRightsCharacter;

                    if (Name[0] == '~') SortCharacter = (char)MainWindow.SortCharacters.OwnerCharacter;
                    else if (Name[0] == '&') SortCharacter = (char)MainWindow.SortCharacters.SuperOpCharacter;
                    else if (Name[0] == '@') SortCharacter = (char)MainWindow.SortCharacters.OpCharacter;
                    else if (Name[0] == '%') SortCharacter = (char)MainWindow.SortCharacters.HalfopCharacter;
                    else if (Name[0] == '+') SortCharacter = (char)MainWindow.SortCharacters.VoiceCharacter;

                    ChannelNames.Add(NewName, SortCharacter + Channel.GetNameWithoutRights(Name));
                }
            }

            // We need to invoke 
            mainWindow.UsersTreeView.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate()
            {
                // Get each Item as a pair
                foreach (KeyValuePair<string, string> Item in ChannelNames)
                {
                    TreeViewItem UserItem = new TreeViewItem();

                    // Set the header
                    UserItem.Header = Item.Key;
                    // Filter out the invalid characters
                    UserItem.Name = System.Text.RegularExpressions.Regex.Replace(Item.Value, "[^a-zA-Z0-9]", "");

                    mainWindow.UsersTreeView.Items.Add(UserItem);
                }

                // Now sort the UsersTreeView alphabetically
                mainWindow.UsersTreeView.Items.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", System.ComponentModel.ListSortDirection.Ascending));
            }));
        }

        /// <summary>
        /// This function appends a string to the channel's text
        /// </summary>
        /// <param name="outputLine">The outputline to write</param>
        /// <param name="appendTimestamp">If this bool is set to true, the method prepends a timestamp before the string</param>

        public void SendText(string outputLine, bool appendTimestamp = true)
        {
            if (appendTimestamp) mainWindow.UserInterface.FormatTimestamp(ref outputLine);

            Channel.Text += outputLine;

            // We're currently looking at the channel that was talked in, just write it to the textbox.
            if (mainWindow.CurrentChannelWindow == Channel.Index)
            {
                mainWindow.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
                {
                    new System.Threading.Tasks.Task(() => { mainWindow.Colors.HandleColors(outputLine); }).Start();
                }));
            }
        }

        /// <summary>
        /// This method removes the ChannelWindow from the TreeView
        /// </summary>

        public void Remove()
        {
            // And now remove it from the server list.
            ServerWindow.List[ServerIndex].ServerTreeViewItem.Items.Remove(ChannelTreeViewItem);

            // And part the channel.
            ChannelWindow.List[Channel.Index] = null;
        }
    }
}
